#include "ibp_util.h"

int HexExpand( char *HexBuf , int HexBufLen , char *AscBuf )
{
	int     i,j=0;
	char    c;
	
	for(i=0;i<HexBufLen;i++){
		c=(HexBuf[i]>>4)&0x0f;
		if(c<=9) AscBuf[j++]=c+'0';
		else AscBuf[j++]=c+'A'-10;
		
		c=HexBuf[i]&0x0f;
		if(c<=9) AscBuf[j++]=c+'0';
		else AscBuf[j++]=c+'A'-10;
	}
	AscBuf[j]=0;
	return(0);
}

int HexFold( char *AscBuf , int AscBufLen , char *HexBuf )
{
	int		i,j=0,k=1,r=0;
	char		c;
	char		uc;

	if(((int)strlen(AscBuf)<AscBufLen)||(strlen(AscBuf)==0))
		return -1;

	uc=0;
	for(i=0;i<AscBufLen;i++){
		if((AscBuf[i]>='0')&&(AscBuf[i]<='9')) 
						c=(AscBuf[i]-'0')&0x0f;
		else if((AscBuf[i]>='A')&&(AscBuf[i]<='F')) 
						c=(AscBuf[i]-'A'+10)&0x0f;
			else if((AscBuf[i]>='a')&&(AscBuf[i]<='f'))
						c=(AscBuf[i]-'a'+10)&0x0f;
				else {
					r=-1;
					break;
					}
		uc|=(unsigned char)(c<<(k*4));
		k--;
		if(k<0){
			HexBuf[j]=uc;
			uc=0;
			k=1; j++;
			}
		}
	if(k==0) HexBuf[j]=uc;
	return(r);
}

int Encoding_BASE64( char *dec , int declen , char *enc , int *enclen )
{
	int		len ;
	
	if( enclen )
		if( (*enclen) < BASE64_ENCODING_NEWLEN(declen) )
			return -1;
	
	len = EVP_EncodeBlock( (unsigned char*)enc , (unsigned char*)dec , declen ) ;
	if( len < 0 )
		return -2;
	
	if( enclen )
		(*enclen) = len ;
	
	return 0;
}

int Decoding_BASE64( char *enc , int enclen , char *dec , int *declen )
{
	int		len ;
	
	if( declen )
		if( (*declen) < BASE64_DECODING_NEWLEN(enclen) )
			return -1;
	
	len = EVP_DecodeBlock( (unsigned char*)dec , (unsigned char*)enc , enclen );
	if( len < 0 )
		return -2;
	
	if( declen )
		(*declen) = len ;
	
	return 0;
}

void Generate3DesKey( char *key , int key_len )
{
	int		i ;
	char	*p = NULL ;
	
	srand( time(NULL) );
	
	for( i = 0 , p = key ; i < key_len ; i++ , p++ )
	{
		(*p) = (char)rand() ;
	}
	
	return;
}

int Encrypt_3DES_192bits( char *key_192bits , char *decrypt , int decrypt_len , char *encrypt , int *encrypt_len , char *init_vector )
{
	unsigned char		key[ 8 + 1 ] ;
	DES_key_schedule	ks1 ;
	DES_key_schedule	ks2 ;
	DES_key_schedule	ks3 ;
	
	unsigned char		ivec[ 24 + 1 ] ;
	
	if( decrypt_len < 0 )
		return -1;
	if( decrypt_len == 0 )
		return 0;
	
	memcpy( key , key_192bits , 8 );
        DES_set_key_unchecked( (const_DES_cblock *)key , & ks1 );
	memcpy( key , key_192bits + 8 , 8 );
        DES_set_key_unchecked( (const_DES_cblock *)key , & ks2 );
	memcpy( key , key_192bits + 8 + 8 , 8 );
        DES_set_key_unchecked( (const_DES_cblock *)key , & ks3 );
	
	if( encrypt_len )
	{
		(*encrypt_len) = ((decrypt_len-1)/8+1)*8 ;
		if( (*encrypt_len) < 0 )
			return -2;
	}
	
	if( init_vector == NULL )
	{
		memset( ivec , 0x00 , sizeof(ivec) );
	}
	else
	{
		memcpy( ivec , init_vector , sizeof(ivec)-1 );
	}
	
	DES_ede3_cbc_encrypt( (unsigned char *)decrypt , (unsigned char *)encrypt , decrypt_len , & ks1 , & ks2 , & ks3 , (DES_cblock*)ivec , DES_ENCRYPT );
	
	if( init_vector )
		memcpy( init_vector , ivec , sizeof(ivec)-1 );
	
	return 0;
}

int Decrypt_3DES_192bits( char *key_192bits , char *encrypt , int encrypt_len , char *decrypt , int *decrypt_len , char *init_vector )
{
	unsigned char		key[ 8 + 1 ] ;
	DES_key_schedule	ks1 ;
	DES_key_schedule	ks2 ;
	DES_key_schedule	ks3 ;
	
	unsigned char		ivec[ 24 + 1 ] ;
	
	if( encrypt_len < 0 )
		return -1;
	if( encrypt_len == 0 )
		return 0;
	
	memcpy( key , key_192bits , 8 );
        DES_set_key_unchecked( (const_DES_cblock *)key , & ks1 );
	memcpy( key , key_192bits + 8 , 8 );
        DES_set_key_unchecked( (const_DES_cblock *)key , & ks2 );
	memcpy( key , key_192bits + 8 + 8 , 8 );
        DES_set_key_unchecked( (const_DES_cblock *)key , & ks3 );
	
	if( decrypt_len )
	{
		(*decrypt_len) = ((encrypt_len-1)/8+1)*8 ;
		if( (*decrypt_len) < 0 )
			return -2;
	}
	
	if( init_vector == NULL )
	{
		memset( ivec , 0x00 , sizeof(ivec) );
	}
	else
	{
		memcpy( ivec , init_vector , sizeof(ivec)-1 );
	}
	
	DES_ede3_cbc_encrypt( (unsigned char *)encrypt , (unsigned char *)decrypt , encrypt_len , & ks1 , & ks2 , & ks3 , (DES_cblock*)ivec , DES_DECRYPT );
	
	if( init_vector )
		memcpy( init_vector , ivec , sizeof(ivec)-1 );
	
	return 0;
}

RSA *GenerateRsaKey()
{
	return RSA_generate_key( IBP_RSA_KEYSIZE_BITS , RSA_F4 , NULL , NULL ) ;
}

RSA *ReadPublicKeyFile( char *key_filename )
{
	FILE		*fp = NULL ;
	RSA		*rsa = NULL ;
	
	fp = fopen( key_filename , "rb" ) ;
	if( fp == NULL )
		return NULL;
	
	rsa = d2i_RSAPublicKey_fp( fp , NULL ) ;
	fclose( fp );
	return rsa;
}

RSA *ReadPrivateKeyFile( char *key_filename )
{
	FILE		*fp = NULL ;
	RSA		*rsa = NULL ;
	
	fp = fopen( key_filename , "rb" ) ;
	if( fp == NULL )
		return NULL;
	
	rsa = d2i_RSAPrivateKey_fp( fp , NULL ) ;
	fclose( fp );
	return rsa;
}

int WritePublicKeyFile( RSA *rsa , char *key_filename )
{
	FILE		*fp = NULL ;
	
	int		nret = 0 ;
	
	fp = fopen( key_filename , "wb" ) ;
	if( fp == NULL )
		return -1;
	
	nret = i2d_RSAPublicKey_fp( fp , rsa ) ;
	fclose( fp );
	if( nret == 1 )
		return 0;
	else
		return -2;
}

int WritePrivateKeyFile( RSA *rsa , char *key_filename )
{
	FILE		*fp = NULL ;
	
	int		nret = 0 ;
	
	fp = fopen( key_filename , "wb" ) ;
	if( fp == NULL )
		return -1;
	
	nret = i2d_RSAPrivateKey_fp( fp , rsa ) ;
	fclose( fp );
	if( nret == 1 )
		return 0;
	else
		return -2;
}

RSA *AllocPublicKey( char *key , int key_len )
{
	return d2i_RSAPublicKey( NULL , (const unsigned char **) & key , (long)key_len );
}

RSA *AllocPrivateKey( char *key , int key_len )
{
	return d2i_RSAPrivateKey( NULL , (const unsigned char **) & key , (long)key_len );
}

char *DumpPublicKey( RSA *rsa , int *p_key_len )
{
	char	*key = NULL ;
	
	(*p_key_len) = i2d_RSAPublicKey( rsa , NULL ) ;
	key = (char*)malloc( (*p_key_len) ) ;
	if( key == NULL )
		return NULL;
	(*p_key_len) = i2d_RSAPublicKey( rsa , (unsigned char **) & key ) ;
	
	return key ;
}

char *DumpPrivateKey( RSA *rsa , int *p_key_len )
{
	char	*key = NULL ;
	
	(*p_key_len) = i2d_RSAPrivateKey( rsa , NULL ) ;
	key = (char*)malloc( (*p_key_len) ) ;
	if( key == NULL )
		return NULL;
	(*p_key_len) = i2d_RSAPrivateKey( rsa , (unsigned char **) & key ) ;
	
	return key ;
}

void FreeRsaKey( RSA *rsa )
{
	RSA_free( rsa );
	
	return;
}

int Encrypt_RSA( RSA *rsa , int type , char *decrypt , int decrypt_len , char *encrypt , int *encrypt_len )
{
	int		len ;
	
	if( decrypt_len == -1 )
		return -1;
	if( RSA_size(rsa) > decrypt_len )
		return -2;
	RSAPADDING_RESIZE( decrypt_len , type )
	
	len = RSA_public_encrypt( decrypt_len , (unsigned char *)decrypt , (unsigned char *)encrypt , rsa , type ) ;
	if( len < 0 )
		return -2;
	
	if( encrypt_len )
		(*encrypt_len) = (int)len ;
	
	return 0;
}

int Decrypt_RSA( RSA *rsa , int type , char *encrypt , int encrypt_len , char *decrypt , int *decrypt_len )
{
	int		len ;
	
	if( encrypt_len == -1 )
		return -1;
	if( RSA_size(rsa) > encrypt_len )
		return -2;
	
	len = RSA_private_decrypt( encrypt_len , (unsigned char *)encrypt , (unsigned char *)decrypt , rsa , type ) ;
	if( len < 0 )
		return -2;
	
	if( decrypt_len )
		(*decrypt_len) = (int)len ;
	
	return 0;
}

